package br.ufrrj.im.redes.view;


import javax.swing.JFrame;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.LayoutStyle.ComponentPlacement;
import java.awt.Color;

import javax.swing.JFormattedTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JList;
import javax.swing.border.LineBorder;

import br.ufrrj.im.redes.logic.GameLogic;
import br.ufrrj.im.redes.model.Message;
import br.ufrrj.im.redes.model.ResultGameMessage;
import br.ufrrj.im.redes.model.UpdateGameMessageForGamer;
import br.ufrrj.im.redes.util.Constants;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.ArrayList;

public class GamerWindow {

	private JFrame frmJogoMaiorNmero;
	private JFormattedTextField textField_Prime;
	private JPanel panel;
	private JPanel panel_1;
	private JPanel panel_2 ;
	private JList<String> list;
	private JButton btnDefinir;
	private JLabel lblQuantidadeMximaDe;
	private JLabel lblUsurio;
	private JLabel lbl_User;
	private JLabel lblTempo;
	private JLabel lbl_AllTime;
	private JLabel lblTempoRestante;
	private JLabel lbl_RemainderTime;
	private JLabel lblTentativasRestante;
	private JLabel lbl_Attempts;
	private JLabel lblOPrimoSelecionado;
	private JLabel lbl_primo;
	
	private ArrayList<String> updatesList;
	
	private long selectedPrime;
	private int currentAttempts;
	private Timer timerGame;
	private Timer timerCountDown;
	private int currentTime;
	private int remainderTime;
	
	private GameLogic gameLogic;

	
	private void setAnswer(Long prime){
		
		if(GameLogic.validateAnswer(prime.longValue(), gameLogic.getRangePrime())){
			
			definePrime(prime.longValue());
			currentAttempts--;
			this.selectedPrime = prime.longValue();
			
			if (timerCountDown == null)
				startCountDown();
			else
				remainderTime = Constants.REMAINDER_TIME_START;
			
			writeStatus();
			JOptionPane.showMessageDialog(frmJogoMaiorNmero, "Número primo: " + prime.longValue() + " definido com sucesso.", "Definir primo", JOptionPane.INFORMATION_MESSAGE);
		}
		else
			JOptionPane.showMessageDialog(frmJogoMaiorNmero, "O número inserido: " + prime.longValue() + " não é válido!\nVerifique se este número realmente é primo ou se este atende o critérido de tamanho máximo.", "Erro ao validar primo", JOptionPane.OK_OPTION);
		
	}
		
	private void definePrime(long prime){
		
	}
	
	public void showWindow(){
		this.frmJogoMaiorNmero.setVisible(true);
	}

	private void exit(){		
		
		int msgBox = JOptionPane.showConfirmDialog(frmJogoMaiorNmero,
				"Você realmente deseja sair? \nSua conexão com o servidor será encerrada.", "Sair",
				JOptionPane.YES_NO_OPTION);

		// Sim ou não
		if (msgBox == JOptionPane.YES_OPTION){
			disconnectGame();
			
			frmJogoMaiorNmero.setVisible(false);
			LoginClientWindow loginWindow = new LoginClientWindow(this.gameLogic.getUser().getName());
			loginWindow.showWindow();
			
			//System.exit(1); //volta para a tela de login, não encerra mais o processo
			
			
		}
	}
	
	
	private void disconnectGame(){
		
	}	

	/**
	 * Create the application.
	 */
	public GamerWindow(GameLogic gameLogic, int attemptsStart) {
		
		this.gameLogic = gameLogic;
		
		this.currentAttempts = attemptsStart;
		remainderTime = Constants.REMAINDER_TIME_START;
		
		//lista de atualizações recebidas do servidor
		this.updatesList = new ArrayList<String>();
		
		//inicailiza o timer
		startTimer();
		
		initialize();
		
		//cria uma thread para receber atualizações do servidor
		getUpdates();
	}
	
	private void getUpdates() {
		Thread updateThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				Message message = null;
				
				do {
					try {
						
						message = gameLogic.getUpdateGame();
						
						if(message instanceof UpdateGameMessageForGamer){
							remainderTime = Constants.REMAINDER_TIME_START;
							writeUpdates((UpdateGameMessageForGamer) message);
						}										
						
					} catch (ClassNotFoundException | IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				} while (!(message instanceof ResultGameMessage));
				
				//encerra conexões com o servidor e desabilita a definição de novas jogadas
				endGame();
				
				//exibe o resultado do jogo
				showResultGame((ResultGameMessage) message);
			}
		});
		
		updateThread.start();
	}
	
	private void writeStatus(){
		lbl_primo.setText(String.valueOf(selectedPrime));
		lbl_Attempts.setText(String.valueOf(currentAttempts));
	}
	
	private void writeUpdates(UpdateGameMessageForGamer updateMessage){
		updatesList.add(updateMessage.getUpdate());
		list.setListData((String[]) updatesList.toArray());
	}
	
	private void endGame(){
		
		btnDefinir.setEnabled(false);
		
		try {
			gameLogic.closeConnectionsAndStreams();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			JOptionPane.showMessageDialog(frmJogoMaiorNmero, e.toString(), "Erro ao encerrar conexões com servidor", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
		}
		
	}
	
	private void showResultGame(ResultGameMessage resultMessage){
		
	}

	private void startCountDown(){
		
		ActionListener action = new ActionListener() {  
            public void actionPerformed(ActionEvent e) {  
                
            	if(remainderTime >= 0)
            		lbl_RemainderTime.setText(remainderTime-- + "");
            	else{
            		timerCountDown.stop();
            		endGame();
            	}
            		
            }
        };  
        
        this.timerCountDown = new Timer(1000, action);  
        this.timerCountDown.start(); 
	}
	
	private void startTimer() {  
        
		ActionListener action = new ActionListener() {  
            public void actionPerformed(ActionEvent e) {  
            	if(remainderTime >= 0)
            		lbl_AllTime.setText(++currentTime + "");
            	else{
            		timerGame.stop();
            		endGame();
            	}
            }  
        };  
        
        this.timerGame = new Timer(1000, action);  
        this.timerGame.start();  
    }  

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmJogoMaiorNmero = new JFrame();
		frmJogoMaiorNmero.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				
				exit();
				
			}
		});
		frmJogoMaiorNmero.setResizable(false);
		frmJogoMaiorNmero.setTitle("Jogo Leilão dos Números Primos");
		frmJogoMaiorNmero.setBounds(100, 100, 540, 460);
		frmJogoMaiorNmero.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		
		panel = new JPanel();
		panel.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "Informa\u00E7\u00F5es", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "Insira seu n\u00FAmero primo", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		panel_2 = new JPanel();
		panel_2.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "Atualiza\u00E7\u00F5es", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		GroupLayout groupLayout = new GroupLayout(frmJogoMaiorNmero.getContentPane());
		groupLayout.setHorizontalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
						.addComponent(panel, Alignment.LEADING, 0, 0, Short.MAX_VALUE)
						.addGroup(Alignment.LEADING, groupLayout.createParallelGroup(Alignment.TRAILING, false)
							.addComponent(panel_2, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
							.addComponent(panel_1, Alignment.LEADING, 0, 0, Short.MAX_VALUE)))
					.addContainerGap(14, Short.MAX_VALUE))
		);
		groupLayout.setVerticalGroup(
			groupLayout.createParallelGroup(Alignment.LEADING)
				.addGroup(groupLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, 124, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 85, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel_2, GroupLayout.DEFAULT_SIZE, 204, Short.MAX_VALUE)
					.addContainerGap())
		);
		
		JScrollPane scrollPane = new JScrollPane();
		GroupLayout gl_panel_2 = new GroupLayout(panel_2);
		gl_panel_2.setHorizontalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 502, Short.MAX_VALUE)
		);
		gl_panel_2.setVerticalGroup(
			gl_panel_2.createParallelGroup(Alignment.LEADING)
				.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 155, Short.MAX_VALUE)
		);
		
		list = new JList<String>();
		scrollPane.setViewportView(list);
		panel_2.setLayout(gl_panel_2);
		
		textField_Prime = new JFormattedTextField();
		textField_Prime.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
					
			}
		});
		textField_Prime.setColumns(10);
		
		btnDefinir = new JButton("Definir Primo");
		btnDefinir.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				setAnswer(Long.parseLong(textField_Prime.getText()));
					
				if (currentAttempts == 0)
					btnDefinir.setEnabled(false);
				
				
			}
		});
		btnDefinir.setMnemonic('D');
		
		lblQuantidadeMximaDe = new JLabel("Quantidade máxima de dígitos decimais:");
		
		JLabel lbl_Length = new JLabel(String.valueOf(this.gameLogic.getRangePrime()));
		lbl_Length.setFont(new Font("Dialog", Font.PLAIN, 12));
		GroupLayout gl_panel_1 = new GroupLayout(panel_1);
		gl_panel_1.setHorizontalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel_1.createParallelGroup(Alignment.LEADING)
						.addComponent(textField_Prime, GroupLayout.PREFERRED_SIZE, 298, GroupLayout.PREFERRED_SIZE)
						.addGroup(gl_panel_1.createSequentialGroup()
							.addComponent(lblQuantidadeMximaDe)
							.addGap(18)
							.addComponent(lbl_Length, GroupLayout.PREFERRED_SIZE, 46, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
					.addGap(3)
					.addComponent(btnDefinir)
					.addContainerGap())
		);
		gl_panel_1.setVerticalGroup(
			gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
					.addGroup(gl_panel_1.createParallelGroup(Alignment.BASELINE)
						.addComponent(textField_Prime, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(btnDefinir))
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addGroup(gl_panel_1.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblQuantidadeMximaDe)
						.addComponent(lbl_Length))
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		panel_1.setLayout(gl_panel_1);
	
		
		lblUsurio = new JLabel("Usuário:");
		
		lbl_User = new JLabel("user");
		this.lbl_User.setText(this.gameLogic.getUser().getName());
		lbl_User.setFont(new Font("Dialog", Font.PLAIN, 12));
		
		lblTempo = new JLabel("Tempo de jogo:");
		
		lbl_AllTime = new JLabel("0");
		lbl_AllTime.setFont(new Font("Dialog", Font.PLAIN, 12));
		
		lblTempoRestante = new JLabel("Tempo restante:");
		
		lbl_RemainderTime = new JLabel("");
		lbl_RemainderTime.setForeground(Color.RED);
		lbl_RemainderTime.setFont(new Font("Dialog", Font.PLAIN, 12));
		
		lblTentativasRestante = new JLabel("Tentativas restantes:");
		
		lbl_Attempts = new JLabel(String.valueOf(currentAttempts));
		lbl_Attempts.setFont(new Font("Dialog", Font.PLAIN, 12));
		
		lblOPrimoSelecionado = new JLabel("O primo selecionado é:");
		
		lbl_primo = new JLabel("n.a.");
		lbl_primo.setFont(new Font("Dialog", Font.PLAIN, 12));
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_panel.createSequentialGroup()
							.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(lblUsurio)
									.addPreferredGap(ComponentPlacement.RELATED)
									.addComponent(lbl_User, GroupLayout.PREFERRED_SIZE, 117, GroupLayout.PREFERRED_SIZE))
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(lblTentativasRestante)
									.addPreferredGap(ComponentPlacement.RELATED)
									.addComponent(lbl_Attempts, GroupLayout.PREFERRED_SIZE, 91, GroupLayout.PREFERRED_SIZE)))
							.addPreferredGap(ComponentPlacement.RELATED, 24, Short.MAX_VALUE)
							.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addComponent(lblTempoRestante, GroupLayout.PREFERRED_SIZE, 127, GroupLayout.PREFERRED_SIZE)
								.addComponent(lblTempo))
							.addPreferredGap(ComponentPlacement.RELATED)
							.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addGroup(gl_panel.createSequentialGroup()
									.addComponent(lbl_RemainderTime, GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
									.addPreferredGap(ComponentPlacement.RELATED))
								.addComponent(lbl_AllTime, GroupLayout.PREFERRED_SIZE, 61, GroupLayout.PREFERRED_SIZE))
							.addGap(4))
						.addGroup(gl_panel.createSequentialGroup()
							.addComponent(lblOPrimoSelecionado)
							.addGap(18)
							.addComponent(lbl_primo, GroupLayout.PREFERRED_SIZE, 231, GroupLayout.PREFERRED_SIZE)
							.addContainerGap())))
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_panel.createParallelGroup(Alignment.TRAILING)
						.addGroup(gl_panel.createSequentialGroup()
							.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
								.addComponent(lblUsurio)
								.addComponent(lbl_User))
							.addPreferredGap(ComponentPlacement.UNRELATED))
						.addGroup(gl_panel.createSequentialGroup()
							.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
								.addComponent(lblTempo)
								.addComponent(lbl_AllTime))
							.addGap(18)))
					.addGroup(gl_panel.createParallelGroup(Alignment.TRAILING)
						.addComponent(lbl_RemainderTime, Alignment.LEADING)
						.addComponent(lblTempoRestante, Alignment.LEADING)
						.addComponent(lbl_Attempts, Alignment.LEADING)
						.addComponent(lblTentativasRestante, Alignment.LEADING))
					.addGap(18)
					.addGroup(gl_panel.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblOPrimoSelecionado)
						.addComponent(lbl_primo))
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		panel.setLayout(gl_panel);
		frmJogoMaiorNmero.getContentPane().setLayout(groupLayout);
	}
}
